﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Web.Services;
using TripLOA.WebService;
using TripLOA.WebService.Serializable;

namespace TripLOA.WebService.Rest
{
    [WebService(Namespace = "http://triploa.cli.di.unipi.it/service/rest/", Name = "RestTrip")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class RestTrip : EndPoint
    {
        private TripCore core;

        #region RestTrip Constructors
        public RestTrip()
        {
            core = TripCore.Istance();
        }
        #endregion

        #region RestTrip Methods

        /// <summary>
        /// Get a specific Trip
        /// </summary>
        /// <param name="_REQUEST">Http GET Parameters</param>
        /// <param name="format">Response format (rest or json)</param>
        /// <returns>Serialized trip</returns>
        /// <example>http://triploa.cli.di.unipi.it/service/rest/RestTrip.ashx?method=getTrip&trip_id=50</example>
        public string getTrip(NameValueCollection _REQUEST, string format)
        {
            //Validate parameters
            List<WSParameter> parameters = new List<WSParameter>();
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["trip_id"] });
            if (!WsCore.ValidateParameters(parameters))
            {
                //Request contains invalid parameters
                WSError wse = new WSError();
                wse.ErrorType = ErrorType.InvalidParameter;
                wse.Message = "Request contains invalid parameters";
                return Serialization.serialize(wse, typeof(WSError), format);
            }
            
            WSTrip wst = core.getTrip(int.Parse(_REQUEST["trip_id"]));
            return Serialization.serialize(wst, typeof(WSTrip), format);
        }

        public string GetTripDetails(NameValueCollection _REQUEST, string format)
        {
            //Validate parameters
            List<WSParameter> parameters = new List<WSParameter>();
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["trip_id"] });
            if (!WsCore.ValidateParameters(parameters))
            {
                //Request contains invalid parameters
                WSError wse = new WSError();
                wse.ErrorType = ErrorType.InvalidParameter;
                wse.Message = "Request contains invalid parameters";
                return Serialization.serialize(wse, typeof(WSError), format);
            }

            WSFullTrip wst = core.GetTripDetails(_REQUEST["auth_token"], int.Parse(_REQUEST["trip_id"]));
            return Serialization.serialize(wst, typeof(WSFullTrip), format);
        }

        /// <summary>
        /// Book a trip
        /// </summary>
        /// <param name="_REQUEST">Request parameters</param>
        /// <param name="format">Response format (rest or json)</param>
        /// <returns>Serialized WSBool</returns>
        /// <example>http://triploa.cli.di.unipi.it/service/rest/RestTrip.ashx?method=BookTrip&trip_id=50</example>
        public string BookTrip(NameValueCollection _REQUEST, string format)
        {
            //Validate parameters
            List<WSParameter> parameters = new List<WSParameter>();
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["trip_id"] });
            if (!WsCore.ValidateParameters(parameters))
            {
                //Request contains invalid parameters
                WSError wse = new WSError();
                wse.ErrorType = ErrorType.InvalidParameter;
                wse.Message = "Request contains invalid parameters";
                return Serialization.serialize(wse, typeof(WSError), format);
            }
            WSBool resp = core.BookTrip(_REQUEST["auth_token"], int.Parse(_REQUEST["trip_id"]));
            return Serialization.serialize(resp, typeof(WSBool), format);
        }

        public string CancelTrip(NameValueCollection _REQUEST, string format)
        {
            //Validate parameters
            List<WSParameter> parameters = new List<WSParameter>();
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["trip_id"] });
            if (!WsCore.ValidateParameters(parameters))
            {
                //Request contains invalid parameters
                WSError wse = new WSError();
                wse.ErrorType = ErrorType.InvalidParameter;
                wse.Message = "Request contains invalid parameters";
                return Serialization.serialize(wse, typeof(WSError), format);
            }
            WSBool resp = core.CancelTrip(_REQUEST["auth_token"], int.Parse(_REQUEST["trip_id"]));
            return Serialization.serialize(resp, typeof(WSBool), format);
        }

        public string AddTripToFavorites(NameValueCollection _REQUEST, string format)
        {
            WSBool resp = core.AddTripToFavorites(_REQUEST["auth_token"], int.Parse(_REQUEST["trip_id"]));
            return Serialization.serialize(resp, typeof(WSBool), format);
        }

        public string RemoveTripFromFavorites(NameValueCollection _REQUEST, string format)
        {
            //Validate parameters
            List<WSParameter> parameters = new List<WSParameter>();
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["trip_id"] });
            if (!WsCore.ValidateParameters(parameters))
            {
                //Request contains invalid parameters
                WSError wse = new WSError();
                wse.ErrorType = ErrorType.InvalidParameter;
                wse.Message = "Request contains invalid parameters";
                return Serialization.serialize(wse, typeof(WSError), format);
            }
            WSBool resp = core.RemoveTripFromFavorites(_REQUEST["auth_token"], int.Parse(_REQUEST["trip_id"]));
            return Serialization.serialize(resp, typeof(WSBool), format);
        }

        public string IsBooked(NameValueCollection _REQUEST, string format)
        {
            //Validate parameters
            List<WSParameter> parameters = new List<WSParameter>();
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["trip_id"] });
            if (!WsCore.ValidateParameters(parameters))
            {
                //Request contains invalid parameters
                WSError wse = new WSError();
                wse.ErrorType = ErrorType.InvalidParameter;
                wse.Message = "Request contains invalid parameters";
                return Serialization.serialize(wse, typeof(WSError), format);
            }
            WSBool resp = core.IsBooked(_REQUEST["auth_token"], int.Parse(_REQUEST["trip_id"]));
            return Serialization.serialize(resp, typeof(WSBool), format);
        }

        public string IsInFavorites(NameValueCollection _REQUEST, string format)
        {
            //Validate parameters
            List<WSParameter> parameters = new List<WSParameter>();
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["trip_id"] });
            if (!WsCore.ValidateParameters(parameters))
            {
                //Request contains invalid parameters
                WSError wse = new WSError();
                wse.ErrorType = ErrorType.InvalidParameter;
                wse.Message = "Request contains invalid parameters";
                return Serialization.serialize(wse, typeof(WSError), format);
            }
            WSBool resp = core.IsInFavorites(_REQUEST["auth_token"], int.Parse(_REQUEST["trip_id"]));
            return Serialization.serialize(resp, typeof(WSBool), format);
        }

        /// <summary>
        /// Returns User's booked trips
        /// </summary>
        /// <param name="_REQUEST">Request parameters</param>
        /// <param name="format">Response format (rest or json)</param>
        /// <returns>Serialized list of trips</returns>
        /// <example>http://triploa.cli.di.unipi.it/service/rest/RestTrip.ashx?method=BookedTrips&auth_token=AUTH_TOKEN&start=0&max=10</example>
        public string BookedTrips(NameValueCollection _REQUEST, string format)
        {
            //Validate parameters
            List<WSParameter> parameters = new List<WSParameter>();
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["start"] });
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["max"] });
            if (!WsCore.ValidateParameters(parameters))
            {
                //Request contains invalid parameters
                WSError wse = new WSError();
                wse.ErrorType = ErrorType.InvalidParameter;
                wse.Message = "Request contains invalid parameters";
                return Serialization.serialize(wse, typeof(WSError), format);
            }

            WSTrip wst = null;
            try
            {
                wst = core.BookedTrips(_REQUEST["auth_token"], int.Parse(_REQUEST["start"]), int.Parse(_REQUEST["max"]));
            }
            catch (FormatException)
            {
                //Wrong parameter exception
                WSError wse = new WSError();
                wse.ErrorType = ErrorType.InvalidParameter;
                wse.Message = "Request contains invalid parameters";
                return Serialization.serialize(wse, typeof(WSError), format);
            }
            return Serialization.serialize(wst, typeof(WSTrip), format);
        }

        public string OfferedTrips(NameValueCollection _REQUEST, string format)
        {
            //Validate parameters
            List<WSParameter> parameters = new List<WSParameter>();
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["start"] });
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["max"] });
            if (!WsCore.ValidateParameters(parameters))
            {
                //Request contains invalid parameters
                WSError wse = new WSError();
                wse.ErrorType = ErrorType.InvalidParameter;
                wse.Message = "Request contains invalid parameters";
                return Serialization.serialize(wse, typeof(WSError), format);
            }

            WSTrip wst = null;
            try
            {
                wst = core.OfferedTrips(_REQUEST["auth_token"], int.Parse(_REQUEST["start"]), int.Parse(_REQUEST["max"]));
            }
            catch (FormatException)
            {
                //Wrong parameter exception
                WSError wse = new WSError();
                wse.ErrorType = ErrorType.InvalidParameter;
                wse.Message = "Request contains invalid parameters";
                return Serialization.serialize(wse, typeof(WSError), format);
            }

            return Serialization.serialize(wst, typeof(WSTrip), format);
        }

        public string FavoritesTrips(NameValueCollection _REQUEST, string format)
        {
            //Validate parameters
            List<WSParameter> parameters = new List<WSParameter>();
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["start"] });
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["max"] });
            if (!WsCore.ValidateParameters(parameters))
            {
                //Request contains invalid parameters
                WSError wse = new WSError();
                wse.ErrorType = ErrorType.InvalidParameter;
                wse.Message = "Request contains invalid parameters";
                return Serialization.serialize(wse, typeof(WSError), format);
            }

            WSTrip wst = null;
            try
            {
                wst = core.FavoritesTrips(_REQUEST["auth_token"], int.Parse(_REQUEST["start"]), int.Parse(_REQUEST["max"]));
            }
            catch (FormatException)
            {
                //Wrong parameter exception
                WSError wse = new WSError();
                wse.ErrorType = ErrorType.InvalidParameter;
                wse.Message = "Request contains invalid parameters";
                return Serialization.serialize(wse, typeof(WSError), format);
            }

            return Serialization.serialize(wst, typeof(WSTrip), format);
        }

        /// <summary>
        /// Create a Trip
        /// </summary>
        /// <param name="_REQUEST">Parameters</param>
        /// <param name="format">Response format (rest or json)</param>
        /// <returns>Serialized response</returns>
        /// <example>Make a request to http://triploa.cli.di.unipi.it/service/rest/RestTrip.ashx?auth_token=AUTH_TOKEN&departure=41.1,12.1&arrival=41.2,12.3&departure_date=2008-05-10&general_notes=Note+Generali&free_seats=4</example>
        public string CreateTrip( NameValueCollection _REQUEST, string format)
        {
            //Validate parameters
            List<WSParameter> parameters = new List<WSParameter>();
            parameters.Add(new WSParameter() { type = typeof(DateTime), value = _REQUEST["departure_date"] });
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["free_seats"] });
            if (!WsCore.ValidateParameters(parameters))
            {
                //Request contains invalid parameters
                WSError wse = new WSError();
                wse.ErrorType = ErrorType.InvalidParameter;
                wse.Message = "Request contains invalid parameters";
                return Serialization.serialize(wse, typeof(WSError), format);
            }
            
            WSInt wsb = core.CreateTrip(_REQUEST["auth_token"],
                                         _REQUEST["departure_coords"],
                                         _REQUEST["arrival_coords"],
                                         DateTime.Parse(_REQUEST["departure_date"]), 
                                         _REQUEST["general_notes"], 
                                         byte.Parse (_REQUEST["free_seats"]));
            return Serialization.serialize(wsb, typeof(WSInt), format);
        }

        /// <summary>
        /// Save a trip. This method is used to create or update a trip.
        /// </summary>
        /// <param name="_REQUEST">The GET Request, it must contain the serialized FullTripInfo (see example)</param>
        /// <param name="format">The response format</param>
        /// <returns>The serialized object</returns>
        /// <example>http://localhost:49700/service/rest/RestTrip.ashx?method=SaveTrip&auth_token=YOUR_AUTH_TOKEN&trip[Draft]=false&trip[FreeSeats]=3&trip[ID]=-1&trip[Notes]=Nessuna&trip[Stages][0][Origin][Coords]=43.72066,10.407337&trip[Stages][0][Destination][Coords]=41.910285,12.476451&trip[Stages][0][EstimatedBudget]=100&trip[Stages][0][EstimatedTime]=300&trip[Stages][0][Vehicle][Id]=6350&trip[Stages][0][Vehicle][VehicleClass]=Car&trip[DepartureDate]=2008-06-10T11:00:00&trip[IsFrequent]=false&trip[DeviationRadius]=5</example>
        public string SaveTrip(NameValueCollection _REQUEST, string format)
        {
            //Create a FullTripInfo
            TripLOA.WebService.Wrappers.FullTripInfo trip = (TripLOA.WebService.Wrappers.FullTripInfo)EndPoint.FillObject(
                EndPoint.CreateRestObject(_REQUEST, "trip"), typeof(TripLOA.WebService.Wrappers.FullTripInfo)
            );

            WSInt wsi = core.SaveTrip(_REQUEST["auth_token"], trip);
            return Serialization.serialize(wsi, typeof(WSInt), format);
        }

        /// <summary>
        /// Delete a trip
        /// </summary>
        /// <param name="_REQUEST"></param>
        /// <param name="format"></param>
        /// <returns></returns>
        public string DeleteTrip(NameValueCollection _REQUEST, string format)
        {
            //Validate parameters
            List<WSParameter> parameters = new List<WSParameter>();
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["trip_id"] });
            if (!WsCore.ValidateParameters(parameters))
            {
                //Request contains invalid parameters
                WSError wse = new WSError();
                wse.ErrorType = ErrorType.InvalidParameter;
                wse.Message = "Request contains invalid parameters";
                return Serialization.serialize(wse, typeof(WSError), format);
            }

            WSBool wsb = core.DeleteTrip(_REQUEST["auth_token"], int.Parse(_REQUEST["trip_id"]));

            return Serialization.serialize(wsb, typeof(WSBool), format);
        }

        /// <summary>
        /// Rest Trip Search
        /// </summary>
        /// <param name="_REQUEST">HTTP Parameters (GET & POST)</param>
        /// <param name="format">Output format (rest/json)</param>
        /// <returns>Serialized string for a TripInfo object</returns>
        /// <example>Make a request to http://triploa.cli.di.unipi.it/service/rest/RestTrip.ashx?method=TripSearch&from=41.100000,12.100000&to=41.120000,12.31000&from_date=2008-04-01&to_date=2008-05-01&start=0&max=10</example>
        public string TripSearch(NameValueCollection _REQUEST, string format)
        {
            //Validate parameters
            List<WSParameter> parameters = new List<WSParameter>();
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["start"] });
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["max"] });
            parameters.Add(new WSParameter() { type = typeof(DateTime), value = _REQUEST["from_date"] });
            parameters.Add(new WSParameter() { type = typeof(DateTime), value = _REQUEST["to_date"] });
            if (!WsCore.ValidateParameters(parameters))
            {
                //Request contains invalid parameters
                WSError wse = new WSError();
                wse.ErrorType = ErrorType.InvalidParameter;
                wse.Message = "Request contains invalid parameters";
                return Serialization.serialize(wse, typeof(WSError), format);
            }

            WSTrip wst = null;
            try
            {
                wst = core.TripSearch(
                            _REQUEST["auth_token"],
                            _REQUEST["from"],
                            _REQUEST["to"],
                            DateTime.Parse(_REQUEST["from_date"]),
                            DateTime.Parse(_REQUEST["to_date"]),
                            int.Parse(_REQUEST["start"]),
                            int.Parse(_REQUEST["max"])
                        );
            }
            catch (FormatException)
            {
                //Wrong parameter exception
                WSError wse = new WSError();
                wse.ErrorType = ErrorType.InvalidParameter;
                wse.Message = "Request contains invalid parameters";
                return Serialization.serialize(wse, typeof(WSError), format);
            }
            return Serialization.serialize(wst, typeof(WSTrip), format);
        }

        /// <summary>
        /// Send a reservation request for a trip
        /// </summary>
        /// <param name="_REQUEST"></param>
        /// <param name="format"></param>
        /// <returns></returns>
        public string RequestReservation(NameValueCollection _REQUEST, string format)
        {
            //Validate parameters
            List<WSParameter> parameters = new List<WSParameter>();
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["trip_id"] });
            parameters.Add(new WSParameter() { type = typeof(uint), value = _REQUEST["seats_no"] });
            parameters.Add(new WSParameter() { type = typeof(int), value = _REQUEST["tolerance"] });
            if (!WsCore.ValidateParameters(parameters))
            {
                //Request contains invalid parameters
                WSError wse = new WSError();
                wse.ErrorType = ErrorType.InvalidParameter;
                wse.Message = "Request contains invalid parameters";
                return Serialization.serialize(wse, typeof(WSError), format);
            }

            WSBool result = core.RequestReservation(_REQUEST["auth_token"],
                   int.Parse(_REQUEST["trip_id"]), _REQUEST["from"], _REQUEST["to"],
                   byte.Parse(_REQUEST["seats_no"]), int.Parse(_REQUEST["tolerance"]),
                   _REQUEST["notes"]);
            return Serialization.serialize(result, typeof(WSBool), format);
        }

        #endregion
    }
}
